package chances.epg.navigator.history;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import chances.epg.commons.utils.URLUtils;
import chances.epg.navigator.EpgConstants;
import chances.epg.navigator.IgnoreHistory;
import chances.epg.navigator.context.AccessContext;
import chances.epg.navigator.context.AccessContextUtils;
import chances.epg.navigator.controller.AjaxReqController;
import chances.epg.play.ctrl.PlayController;
import chances.epg.session.UserSession;
import chances.epg.session.UserSessionHelper;
import chances.epg.session.ctrl.LogonController;

@Component
public class NavigateHistoryInteceptor extends HandlerInterceptorAdapter {
	public static final Logger logger = LoggerFactory.getLogger("navhis");
	public final static String EXTERNAL_BACKURL = "backUrl";

	@Value("${epg.parent.pageurl:'index.jsp'}")
	private String defaultEntry;

	@Override
	public boolean preHandle(HttpServletRequest httpRequest, HttpServletResponse httpResponse, Object handler)
			throws Exception {

		UserSession us = UserSessionHelper.getUserSession(httpRequest);
		if (us == null) {
			return true;
		}
		// 外部系统进入
		String fromType = httpRequest.getParameter(EpgConstants.EPG_ENRTY_TYPE);
		if (StringUtils.isNotBlank(fromType)) {
			logger.debug("fromtype is not null,clear history");
			NavigateHistoryFactory.removeHistory(us);
		}
		
		HistoryResponseWrapper responseWrapper = new HistoryResponseWrapper(httpResponse);
		NavigateHistory history = NavigateHistoryFactory.getHistory(httpRequest, us);
		
		String backUrl = null;
		String returnUrl = httpRequest.getParameter("return");
		if (StringUtils.isNotEmpty(returnUrl)) {
			us.setReturnUrl(returnUrl);
			history.clear();
		}
		if (history.isEmpty()) {
			backUrl = us.getReturnUrl();
		} else {
			String path = httpRequest.getServletPath();
			String contextP = httpRequest.getContextPath();
			if(!path.contains(contextP)){
				path = contextP+path;
			}
			int value = history.indexOf(path);
			if (value > -1) {
				logger.debug("pop url:{}", path);
				history.pop(value);
			}
			if (history.size() > 0) {
				this.appendFocusId(httpRequest, history);
				backUrl = history.getLastPath();
				String contextPath = httpRequest.getContextPath();
				if (!StringUtils.contains(backUrl, contextPath)) {
					backUrl = contextPath + backUrl;
				}
			}
		}
		logger.debug("set return url:{}", backUrl);
		httpRequest.setAttribute(EpgConstants.RETURN_URL, backUrl);
		return super.preHandle(httpRequest, responseWrapper, handler);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse httpResponse, Object handler,
			Exception ex) throws Exception {
		if (ex != null) {
			super.afterCompletion(request, httpResponse, handler, ex);
			return;
		}
		if (isExclude(handler)) {
			return;
		}

		UserSession us = UserSessionHelper.getUserSession(request);
		if (us == null) {
			return;
		}
		// removed
		// 检查当前连接是否需要记录历史
		/*
		 * String remeberFlag = request.getParameter(REMEBER_HIS_FLAG);
		 * if(StringUtils.isNotBlank(remeberFlag) && "0".equals(remeberFlag)){
		 * super.afterCompletion(request, httpResponse, handler, ex); return; }
		 */

		NavigateHistory history = NavigateHistoryFactory.getHistory(request, us);
		AccessContext context = AccessContextUtils.getAccessContext(request);
		if (context != null && !context.isRedirect()) {
			logger.debug("add to history,url:{}", request.getServletPath());
			HistoryEntry historyEntry = NavigateHistoryFactory.createHistoryEntry(request);
			addExternalUrl(request, history);
			history.add(historyEntry);
		}
	}

	/**
	 * 加入外部链接
	 * 
	 * @param request
	 */
	private boolean addExternalUrl(HttpServletRequest request, NavigateHistory history) {
		String returnUrl = request.getParameter(EXTERNAL_BACKURL);
		if (StringUtils.isBlank(returnUrl))
			return false;
		int count = history.size();
		HistoryEntry entry = null;
		int idx = -1;
		for (int i = 0; i < count; i++) {
			entry = history.get(i);
			if (returnUrl.equals(entry.getPath())) {
				idx = i;
				break;
			}
		}
		if (idx > -1) {
			history.pop(idx);
		}
		entry = new HistoryEntry();
		entry.setPath(returnUrl);
		entry.setQueryString(request.getQueryString());
		history.add(entry);
		return true;
	}

	private boolean isExclude(Object handler) {
		if (HandlerMethod.class.isInstance(handler)) {
			HandlerMethod aHanlderMeethod = (HandlerMethod) handler;
			if (aHanlderMeethod.hasMethodAnnotation(IgnoreHistory.class)) {
				return true;
			}
			if (LogonController.class.isInstance(aHanlderMeethod.getBean())
					|| PlayController.class.isInstance(aHanlderMeethod.getBean())
					|| AjaxReqController.class.isInstance(aHanlderMeethod.getBean())) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 
	 * @return
	 */
	private void appendFocusId(HttpServletRequest httpRequest, NavigateHistory history) {
		String lfid = httpRequest.getParameter(EpgConstants.LEAVE_FOCUS_ID);
		HistoryEntry entry = history.peek();
		if (StringUtils.isNotBlank(lfid)) {
			entry.setQueryString(URLUtils.removeParams(entry.getQueryString(), EpgConstants.LEAVE_FOCUS_ID));
			entry.appendParameter(EpgConstants.ENTRY_FOCUS_ID, lfid);
		}

		String ps = httpRequest.getParameter("lps");
		if (StringUtils.isNotEmpty(ps)) {
			entry.appendParameter("ps", ps);
		}
		String p = httpRequest.getParameter("p_idx");
		if (StringUtils.isNotEmpty(p)) {
			entry.appendParameter("p_idx", p);
		}
		String p2 = httpRequest.getParameter("p2_idx");
		if (StringUtils.isNotEmpty(p2)) {
			entry.appendParameter("p2_idx", p2);
		}
	}

	public String getDefaultEntry() {
		return defaultEntry;
	}

	public void setDefaultEntry(String defaultEntry) {
		this.defaultEntry = defaultEntry;
	}

	static class HistoryResponseWrapper extends HttpServletResponseWrapper {
		private int status;

		public HistoryResponseWrapper(HttpServletResponse response) {
			super(response);
		}

		@Override
		public void setStatus(int sc) {
			super.setStatus(sc);
			status = sc;
		}

		public int getStatus() {
			return status;
		}
	}
}
